home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Deutsche Edition 1
/
Deutsche Edition 1.iso
/
amok
/
051-060
/
amok58
/
audiosupport1.1
/
audiosupport.mod
< prev
next >
Wrap
Text File
|
1993-11-04
|
9KB
|
309 lines
(*-------------------------------------------------------------------------
:Program. AudioSupport.mod
:Contents. Easy sound programming
:Author. Christian Stiens
:Address. Heustiege 2, W-4710 Lüdinghausen
:Copyright. PD
:Language. Oberon
:Translator. Amiga Oberon V2.01 [fbs]
:History. V1.0, 25-Aug-90: First release
:History. V1.1, 24-Jul-91: Oberon, +PlayLoopSound
:History. +DontAbort, +SetPriority
-------------------------------------------------------------------------*)
(*---------------------------- DEFINITION --------------------------------
DEFINITION AudioSupport;
CONST
clock = 3563220; (* per = clock / freq *)
left0 = 0;
right0 = 1;
right1 = 2;
left1 = 3;
PROCEDURE SetPriority(pri: SHORTINT);
(* OpenChannel will open channels with priority pri *)
PROCEDURE DontAbort;
(* Program will not be aborted if channels are not free *)
PROCEDURE OpenChannel(mask: SET): SHORTINT;
(* Open one channel of mask and return its channel number *)
PROCEDURE CloseChannel(chan: SHORTINT);
(* Close the channel chan (which not has to be open). All open
channels are closed automatic at program end *)
PROCEDURE PlaySound(chan: SHORTINT; sound: e.ADDRESS; size: LONGINT;
per, vol, cyc: INTEGER);
(* Play the sample at address 'sound' (in chip mem) with period 'per'
(per >= 124), volume 'vol' (0 <= vol <= 64) 'cyc' times (cyc=0 means
forever) *)
PROCEDURE PlayLoopSound(chan: SHORTINT; sound: e.ADDRESS;
oneShot, repeat: LONGINT;
per, vol: INTEGER);
(* Play a looped sound with attack length 'oneShot' and looped
length 'repeat' *)
PROCEDURE StopSound(chan: SHORTINT);
(* Stop the sound in channel 'chan' *)
PROCEDURE CheckSound(chan: SHORTINT): BOOLEAN;
(* Returns 'TRUE' if channel 'chan' is playing at this moment *)
PROCEDURE ModifySound(chan: SHORTINT; per, vol: INTEGER);
(* Modifies frequency and volume of a running sound *)
PROCEDURE WaitSound(chan: SHORTINT);
(* Waits until channel 'chan' has finished his sound *)
PROCEDURE Filter(on: BOOLEAN);
(* Set the Hardware filter on or off *)
----------------------------- END DEFINITION ---------------------------*)
MODULE AudioSupport;
(* $StackChk- $NilChk- $RangeChk- $OvflChk- $ReturnChk- $CaseChk- *)
IMPORT
au : Audio,
e : Exec,
es : ExecSupport,
hw : Hardware,
rq : Requests,
sys: SYSTEM;
CONST
clock * = 3563220;
left0 * = 0;
right0 * = 1;
right1 * = 2;
left1 * = 3;
cantOpen = "Can't open audio channel";
notOpen = "Audio channel not open";
illegal = "Illegal audio channel";
VAR
mp1 : ARRAY 4 OF e.MsgPortPtr;
ioa1,ioa2,ioa3 : ARRAY 4 OF au.IOAudioPtr;
open : ARRAY 4 OF BOOLEAN;
looped : ARRAY 4 OF BOOLEAN;
lastPer,lastVol: ARRAY 4 OF INTEGER;
priority : SHORTINT;
abort : BOOLEAN;
PROCEDURE SetPriority*(pri: SHORTINT);
BEGIN
priority := pri
END SetPriority;
PROCEDURE DontAbort*;
BEGIN
abort := FALSE;
END DontAbort;
PROCEDURE OpenChannel*(mask: SET): SHORTINT;
VAR
allocMask : ARRAY 4 OF SHORTSET;
chan : SHORTINT;
i : INTEGER;
mp : e.MsgPortPtr;
ioa : POINTER TO ARRAY 3 OF au.IOAudio;
BEGIN
IF mask * {0..3} = {} THEN mask := {0..3} END;
mp := es.CreatePort("",0);
IF mp # NIL THEN
ioa := e.AllocMem(sys.SIZE(ioa^),LONGSET{e.memClear,e.public});
IF ioa # NIL THEN
ioa[0].request.message.node.type := e.message;
ioa[0].request.message.length := sys.SIZE(au.IOAudio);
ioa[0].request.message.replyPort := mp;
i := 0;
chan := 0; WHILE chan < 4 DO
IF chan IN mask THEN allocMask[i] := SHORTSET{chan}; INC(i) END;
INC(chan)
END;
ioa[0].request.message.node.pri := priority;
ioa[0].data := sys.ADR(allocMask);
ioa[0].length := i;
IF e.OpenDevice(au.audioName,0,sys.VAL(e.MessagePtr,ioa),LONGSET{})
= 0 THEN
ioa^[1] := ioa^[0];
ioa^[2] := ioa^[0];
CASE sys.VAL(LONGINT,ioa[0].request.unit) OF
1: chan := left0 |
2: chan := right0 |
4: chan := right1 |
8: chan := left1
ELSE
HALT(20);
END;
mp1[chan] := mp;
ioa1[chan] := sys.ADR(ioa[0]);
ioa2[chan] := sys.ADR(ioa[1]);
ioa3[chan] := sys.ADR(ioa[2]);
ioa1[chan].data := 0;
open[chan] := TRUE;
looped[chan] := FALSE;
RETURN chan
END;
e.FreeMem(ioa,sys.SIZE(ioa^));
END;
es.DeletePort(mp)
END;
rq.Assert(~abort,cantOpen);
RETURN -1
END OpenChannel;
PROCEDURE CloseChannel*(chan: SHORTINT);
BEGIN
IF (chan >= 0) & (chan <= 3) & open[chan] THEN
e.CloseDevice(ioa1[chan]);
e.FreeMem(ioa1[chan],3*sys.SIZE(au.IOAudio));
es.DeletePort(mp1[chan]);
open[chan] := FALSE;
END
END CloseChannel;
PROCEDURE CheckChannel(chan: SHORTINT): BOOLEAN;
BEGIN
CASE chan OF
-1 : rq.Assert(~abort,notOpen); RETURN FALSE |
0..3 : IF open[chan] THEN RETURN TRUE
ELSE rq.Assert(~abort,notOpen); RETURN FALSE END
ELSE rq.Assert(FALSE,illegal);
END;
END CheckChannel;
PROCEDURE PlaySound*(chan:SHORTINT; sound:e.ADDRESS; size:LONGINT;
per,vol,cyc:INTEGER);
BEGIN
IF ~CheckChannel(chan) THEN RETURN END;
IF looped[chan] THEN es.AbortIO(ioa2[chan]) END;
es.AbortIO(ioa1[chan]);
IF size > 1 THEN
ioa1[chan].request.command := e.write;
ioa1[chan].request.flags := SHORTSET{au.pervol};
ioa1[chan].data := sound;
ioa1[chan].length := size;
ioa1[chan].period := per;
ioa1[chan].volume := vol;
ioa1[chan].cycles := cyc;
es.BeginIO(ioa1[chan]);
END;
lastPer[chan] := per;
lastVol[chan] := vol;
looped[chan] := FALSE;
END PlaySound;
PROCEDURE PlayLoopSound*(chan:SHORTINT; sound:e.ADDRESS;
oneShot,repeat:LONGINT;
per,vol:INTEGER);
BEGIN
IF oneShot = 0 THEN
PlaySound(chan,sound,repeat,per,vol,0);
RETURN;
END;
IF repeat = 0 THEN
PlaySound(chan,sound,oneShot,per,vol,1);
RETURN;
END;
IF ~CheckChannel(chan) THEN RETURN END;
es.AbortIO(ioa2[chan]);
es.AbortIO(ioa1[chan]);
ioa1[chan].request.command := e.write;
ioa1[chan].request.flags := SHORTSET{au.pervol};
ioa1[chan].data := sound;
ioa1[chan].length := oneShot;
ioa1[chan].period := per;
ioa1[chan].volume := vol;
ioa1[chan].cycles := 1;
es.BeginIO(ioa1[chan]);
ioa2[chan].request.command := e.write;
ioa2[chan].request.flags := SHORTSET{};
ioa2[chan].data := sound+oneShot;
ioa2[chan].length := repeat;
ioa2[chan].cycles := 0;
es.BeginIO(ioa2[chan]);
lastPer[chan] := per;
lastVol[chan] := vol;
looped[chan] := TRUE;
END PlayLoopSound;
PROCEDURE StopSound*(chan: SHORTINT);
BEGIN
IF ~CheckChannel(chan) THEN RETURN END;
IF looped[chan] THEN
es.AbortIO(ioa2[chan]); looped[chan] := FALSE
END;
es.AbortIO(ioa1[chan])
END StopSound;
PROCEDURE CheckSound*(chan: SHORTINT): BOOLEAN;
BEGIN
IF ~CheckChannel(chan) THEN RETURN FALSE END;
RETURN looped[chan] OR ((ioa1[chan].data # 0) & ~e.CheckIO(ioa1[chan]))
END CheckSound;
PROCEDURE ModifySound*(chan:SHORTINT; per,vol: INTEGER);
BEGIN
IF ~CheckChannel(chan) THEN RETURN END;
IF (vol#lastVol[chan]) OR (per#lastPer[chan]) THEN
ioa3[chan].request.command := au.perVol;
ioa3[chan].period := per;
ioa3[chan].volume := vol;
e.OldDoIO(ioa3[chan]);
lastPer[chan] := per;
lastVol[chan] := vol;
END;
END ModifySound;
PROCEDURE WaitSound*(chan: SHORTINT);
BEGIN
IF ~CheckChannel(chan) THEN RETURN END;
IF NOT looped[chan] THEN e.OldWaitIO(ioa1[chan]) END;
END WaitSound;
PROCEDURE Filter*(on: BOOLEAN);
BEGIN
IF on THEN
EXCL(hw.ciaa.pra,hw.led)
ELSE
INCL(hw.ciaa.pra,hw.led)
END
END Filter;
BEGIN
priority := 0;
abort := TRUE;
open[left0] := FALSE;
open[right0] := FALSE;
open[right1] := FALSE;
open[left1] := FALSE;
CLOSE
CloseChannel(left0);
CloseChannel(right0);
CloseChannel(right1);
CloseChannel(left1);
END AudioSupport.